#include "./ctrl.h"
#include "../xlib/gpio.h"
#include "../rtos/mutex.h"

namespace ice_driver {

Ctrl ctrl;

namespace ctrl_impl {

using namespace stm32f1::gpio;
using namespace stm32f1;

using PUMP = PB<0>;
using VALVE = PB<9>;
using FAN = PB<12>;
using DROP_ICE = PB<10>;
using STIR = PB<11>;
using COMPR = PB<13>;

static bool partsFlags[6];
static rtos::lazy::Mutex mutex;
static uint32_t stir_open_count = 0;

}

using namespace ctrl_impl;

void Ctrl::init() {
    mutex.init();
    rcc::enable<
        PUMP, VALVE, FAN, DROP_ICE, STIR, COMPR
    >();

    config<
        Cfg<PUMP, Mode::OUT_50MHz_PP>,
        Cfg<VALVE, Mode::OUT_50MHz_PP>,
        Cfg<FAN, Mode::OUT_50MHz_PP>,
        Cfg<DROP_ICE, Mode::OUT_50MHz_PP>,
        Cfg<STIR, Mode::OUT_50MHz_PP>,
        Cfg<COMPR, Mode::OUT_50MHz_PP>
    >();
    close_all();
}

void Ctrl::stir_motor_open() {
    mutex.lock();   
    if (stir_open_count == 0) {
        open(Parts::STIR);
    }
    stir_open_count ++;
    mutex.un_lock();
}

void Ctrl::stir_motor_close() {
    mutex.lock();
    if (stir_open_count > 0) {
        stir_open_count --;
    }
    if (stir_open_count == 0) {
        close(Parts::STIR);
    }
    mutex.un_lock();
}

void Ctrl::close_all() {
    close(Parts::PUMP);
    close(Parts::VALVE);
    close(Parts::FAN);
    close(Parts::DROP_ICE);
    close(Parts::STIR);
    close(Parts::COMPR);
}

uint8_t Ctrl::state() {
    uint8_t v = 0;
    for (uint8_t i = 0; i < 6; i ++) {
        v |= partsFlags[i] << i;
    }
    return v;
}

void Ctrl::close(Parts parts) {

    switch (parts) {
        case Parts::PUMP: PUMP::clr(); break;
        case Parts::VALVE: VALVE::clr(); break;
        case Parts::FAN: FAN::clr(); break;
        case Parts::DROP_ICE: DROP_ICE::clr(); break;
        case Parts::STIR: STIR::clr(); break;
        case Parts::COMPR: COMPR::clr(); break;
        default: return;
    }
    partsFlags[ static_cast<uint8_t>(parts) ] = false;
}

void Ctrl::open(Parts parts) {
    switch (parts) {
        case Parts::PUMP: PUMP::set(); break;
        case Parts::VALVE: VALVE::set(); break;
        case Parts::FAN: FAN::set(); break;
        case Parts::DROP_ICE: DROP_ICE::set(); break;
        case Parts::STIR: STIR::set(); break;
        case Parts::COMPR: COMPR::set(); break;
        default: return;
    }
    partsFlags[ static_cast<uint8_t>(parts) ] = true;
}

}

